package com.ybg.share.schedule;

import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.ybg.framework.constant.RedisKey;
import com.ybg.framework.core.NetasetSendEmail;
import com.ybg.framework.core.zookeeper.DefaultZkLockConfig;
import com.ybg.framework.core.zookeeper.ZkDistributedLock;
import com.ybg.framework.dto.AbstractJob;
import com.ybg.framework.enums.PbestEnum;
import com.ybg.share.core.dbapi.entity.*;
import com.ybg.share.core.dbapi.service.ShareReceiveEmailService;
import com.ybg.share.core.dbapi.service.ShareStockEmailDataHistoryService;
import com.ybg.share.core.dbapi.service.ShareStockEmailDataService;
import com.ybg.share.core.dbapi.service.ShareStockEvaluateService;
import com.ybg.share.core.dbapi.service.ShareStockPbestService;
import com.ybg.share.core.pbest.vo.PbestEmailVO;
import com.ybg.share.utils.ThreadUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

@Slf4j
@Component
public class AllReportJob {

    @Autowired
    NetasetSendEmail netasetSendEmail;
    @Autowired
    RedisTemplate redisTemplate;
    @Autowired
    ShareReceiveEmailService shareReceiveEmailService;

    @Autowired
    ShareStockPbestService shareStockPbestService;
    @Autowired
    DefaultZkLockConfig defaultZkLockConfig;
    @Autowired
    ShareStockEvaluateService shareStockEvaluateService;
    @Autowired
    ShareStockEmailDataService shareStockEmailDataService;
    @Autowired
    ShareStockEmailDataHistoryService shareStockEmailDataHistoryService;

    static HashMap<Long, ShareStockDayK> shareStockPbestset = new HashMap<Long, ShareStockDayK>(4000);
    static HashMap<Long, ShareFinancialYear> shareStockFinancialSet = new HashMap<>(4000);
    static HashMap<Long,ShareStockEvaluate> shareStockEvaluateSet = new HashMap<>(4000);

    /**
     * 发送推荐股票电子邮件
     */
    @Scheduled(cron = "0 0 8 * * ?")
    public void allReportJob() {
        ZkDistributedLock lock = new ZkDistributedLock(defaultZkLockConfig, "AllReportJob");
        boolean trylock = lock.tryLock();
        if (!trylock) {
            return;
        }
        try {
            QueryWrapper<ShareStockPbest> wrapper = new QueryWrapper<>();
            wrapper.eq(ShareStockPbest.PBEST_NAME, PbestEnum.DAY250.name());
            wrapper.eq(ShareStockPbest.REF_YEAR, DateUtil.thisYear());
            List<ShareStockPbest> shareStockPbests = shareStockPbestService.list(wrapper);
            Object[] dayKRedis = (Object[]) redisTemplate.opsForSet().members(RedisKey.LAST_DAY_K).toArray();
            if (dayKRedis.length == 0) {
                return;
            }
            for (Object dayKRedi : dayKRedis) {
                ShareStockDayK shareStockDayK = JSONObject.parseObject(dayKRedi.toString(), ShareStockDayK.class);
                shareStockPbestset.put(shareStockDayK.getStockId(), shareStockDayK);
            }
            List<PbestEmailVO> contents = new ArrayList<>(dayKRedis.length);
            // System.out.println("shareStockPbestset长度："+shareStockPbestset.size());


            //存入个股利润Map里面
            for (int i = 0; i < 3; i++) {
                int year = DateUtil.thisYear() - 1 - i;
                Object[] members = redisTemplate.opsForSet().members(RedisKey.SHARE_FINANCIAL_YEAR + year).toArray();
                if (members == null || members.length == 0) {
                    continue;
                }
                for (Object member : members) {
                    ShareFinancialYear shareFinancialYear = JSONObject.parseObject(member.toString(), ShareFinancialYear.class);
                    if (shareStockFinancialSet.get(shareFinancialYear.getStockId()) != null) {
                        //已经有最新的就不用在查了
                        continue;
                    }
                    shareStockFinancialSet.put(shareFinancialYear.getStockId(), shareFinancialYear);
                }
            }
            //
            log.info("shareStockFinancialSet.size="+shareStockFinancialSet.size());
            QueryWrapper<ShareStockEvaluate> shareStockEvaluateWrapper= new QueryWrapper<>();

            List<ShareStockEvaluate> stockEvaluates = shareStockEvaluateService.list(shareStockEvaluateWrapper);
            for (ShareStockEvaluate stockEvaluate : stockEvaluates) {
                if(stockEvaluate.getStockId()==null){
                    //可能出现不存在的数据所以跳过
                    continue;
                }
                shareStockEvaluateSet.put(stockEvaluate.getStockId(),stockEvaluate);
            }
            log.info("shareStockEvaluateSet.size="+shareStockEvaluateSet.size());
            shareStockEmailDataService.remove( new UpdateWrapper<>());
            for (ShareStockPbest shareStockPbest : shareStockPbests) {
                ShareStockDayK shareStockDayK = shareStockPbestset.get(shareStockPbest.getStockId());
                if (shareStockDayK == null) {
                    continue;
                }
                PbestEmailVO vo = new PbestEmailVO();
                BeanUtils.copyProperties(shareStockPbest, vo);
                vo.setPrice(shareStockDayK.getClosePrice());
                vo.setOddsRatio(vo.getSellPrice().subtract(vo.getPrice()).divide(vo.getSellPrice().subtract(vo.getBuyPrice()), 2));
                ShareStockEvaluate shareStockEvaluate = shareStockEvaluateSet.get(vo.getStockId());
                if(shareStockEvaluate !=null){
                    vo.setFocus(shareStockEvaluate.getFocus() );
                    vo.setJgcyd(shareStockEvaluate.getJgcyd());
                    vo.setJgcydType(shareStockEvaluate.getJgcydType());
                    vo.setTotalScore(shareStockEvaluate.getTotalScore());
                    vo.setRanking(shareStockEvaluate.getRanking());
                    vo.setPeRation(shareStockEvaluate.getPeRation());

                }else{
                    continue;
                }
                ShareFinancialYear shareFinancialYear = shareStockFinancialSet.get(vo.getStockId());
                if (shareFinancialYear == null) {
                    continue;
                }
                //净利润不够一千万的 直接认为盈利差 不再推荐
                if (shareFinancialYear.getNetProfit().compareTo(new BigDecimal("1000")) < 0) {
                    continue;
                }
                if (vo.getStockName().contains("ST")) {
                    //排除掉退市的股票
                    continue;
                }
                if (vo.getTimes() > 19 && vo.getProfitRate().compareTo(new BigDecimal("0.5")) < 0) {
                    //过滤掉操作次数太多并且利润率太低的股票
                    continue;
                }
                if (vo.getPrice().compareTo(BigDecimal.ONE) < 0) {
                    //价格小于1的 过滤掉
                    continue;
                }
                if (vo.getStockName().contains("B") || vo.getStockName().contains("Ｂ")) {
                    //不推荐B股
                    continue;
                }


                ThreadUtil.execute(new AbstractJob(vo){

                    @Override
                    public void execute() {
                        PbestEmailVO vo= (PbestEmailVO)getParams();
                        ShareStockEmailData emailData= new ShareStockEmailData();
                        BeanUtils.copyProperties(vo,emailData);
                        shareStockEmailDataService.save(emailData);

                        ShareStockEmailDataHistory history= new ShareStockEmailDataHistory();
                        BeanUtils.copyProperties(vo,history);
                        shareStockEmailDataHistoryService.save(history);
                    }
                });



            }


            //存入个股利润Map里面 结束
            //XXX  保存到数据库


        } catch (Exception e) {
            e.printStackTrace();
            log.info("error{}", e);
        } finally {
            lock.unlock();
        }
        //清空内存
        shareStockPbestset = new HashMap<>(4000);
        shareStockFinancialSet = new HashMap<>(4000);
        shareStockEvaluateSet= new HashMap<>(4000);
    }


}

